import importlib
import json
import pkgutil
import sys
from pathlib import Path
from typing import Dict, Any, List
from ..core.tool import Tool
from ..utils.logger import AppLogger


class PluginAPI:
    def __init__(self, register_tool, register_category):
        self._register_tool = register_tool
        self._register_category = register_category

    def add_tool(self, tool: Tool) -> None:
        self._register_tool(tool)

    def add_category(self, category_name: str, icon: str = "") -> None:
        self._register_category(category_name, icon)


class PluginManager:
    def __init__(self):
        self.logger = AppLogger()
        self.plugins: Dict[str, Any] = {}
        self._loaded_plugins: List[str] = []
        self.plugins_path = Path("plugins")
        self.plugins_path.mkdir(exist_ok=True)

    def discover_plugins(self) -> None:
        for finder, name, _ in pkgutil.iter_modules([str(self.plugins_path)]):
            plugin_path = self.plugins_path / name
            meta_file = plugin_path / "plugin.json"

            if meta_file.exists():
                try:
                    with open(meta_file, "r") as f:
                        meta = json.load(f)
                        self.plugins[name] = {
                            "name": meta.get("name", name),
                            "version": meta.get("version", "1.0.0"),
                            "description": meta.get("description", ""),
                            "module": f"plugins.{name}",
                            "enabled": True
                        }
                except Exception as e:
                    self.logger.error(f"Plugin {name} metadata error: {str(e)}")

    def load_plugins(self, register_tool_cb, register_category_cb) -> None:
        api = PluginAPI(register_tool_cb, register_category_cb)

        for plugin_name, plugin_info in self.plugins.items():
            if plugin_info["enabled"]:
                try:
                    module = importlib.import_module(plugin_info["module"])
                    if hasattr(module, "initialize"):
                        module.initialize(api)
                        self._loaded_plugins.append(plugin_name)
                        self.logger.info(f"Loaded plugin: {plugin_name}")
                except Exception as e:
                    self.logger.error(f"Failed to load {plugin_name}: {str(e)}")

    def unload_plugin(self, plugin_name: str) -> bool:
        try:
            if plugin_name in sys.modules:
                del sys.modules[self.plugins[plugin_name]["module"]]
            self._loaded_plugins.remove(plugin_name)
            self.logger.info(f"Unloaded plugin: {plugin_name}")
            return True
        except Exception as e:
            self.logger.error(f"Unload failed: {str(e)}")
            return False

    def reload_plugin(self, plugin_name: str) -> None:
        if self.unload_plugin(plugin_name):
            try:
                module = importlib.reload(
                    importlib.import_module(self.plugins[plugin_name]["module"])
                )
                if hasattr(module, "initialize"):
                    module.initialize(self.api)
                self.logger.info(f"Reloaded plugin: {plugin_name}")
            except Exception as e:
                self.logger.error(f"Reload failed: {str(e)}")

    def add_category(self, category_name, icon=""):
        if category_name not in self.custom_categories:
            icon_img = self.icons.get_icon(icon) or self.icons.folder
            self.custom_categories[category_name] = {
                "icon": icon_img,
                "tools": []
            }
            self.tree.insert("", "end",
                             text=category_name,
                             image=icon_img
                             )

    def add_tool(self, tool: Tool):
        parent = self._find_category_node(tool.category)
        if not parent:
            self.add_category(tool.category)
            parent = self._find_category_node(tool.category)

        self.tree.insert(
            parent, "end",
            text=tool.name,
            values=("stopped"),
            image=self.icons.get_icon(tool.icon),
            tags=(tool.name,)
        )
        self.custom_categories[tool.category]["tools"].append(tool)

    def _find_category_node(self, category_name):
        for child in self.tree.get_children():
            if self.tree.item(child, "text") == category_name:
                return child
        return None


class BasePlugin:
    @staticmethod
    def initialize(api: PluginAPI) -> None:
        raise NotImplementedError("Plugin must implement initialize method")